
package urnoted;

import java.awt.Color;
import java.io.File;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.Timer;

public class Controller {
    Random generator = new Random();
    
    private NoteSynthesizer synthesizer;
    private GUI gui;
    private ControlPanel controlPanel;
    private StaffPanel staffPanel;
    private KeyboardPanel keyboardPanel;
    private ResultsPanel resultsPanel;
    private String skill;
    private String song;
    private Key lastKeyClicked;  // the last key clicked
    private Key currentKey;
    private StaffButton currentStaffButton; 
    private StaffButton lastStaffButtonClicked; // last StaffButton clicked
    
    private Song currSong = null;
    private ArrayList<Song> songList;
    private Note currentNote;
    
    public static final int RAN_LENGTH = 20;
    
    private Timer timer = new Timer();
    
    public Controller() {
    	
        songList = new ArrayList<Song>();
    	loadSongs();
    	
        this.synthesizer = new NoteSynthesizer();
        this.gui = new GUI(this);
        controlPanel = gui.getControlPanel();
        staffPanel = gui.getStaffPanel();
        keyboardPanel = gui.getKeyboardPanel();
        resultsPanel = gui.getResultsPanel();

        this.setSkill("Find Key for Note");
        this.setSong(songList.get(0).getName());
        this.start();
    }
    
    private void generateNewNoteandKey(){
        if(currSong == null){
            currentNote = Note.atIndex(generator.nextInt(
                    Note.values().length));
        }
        else
        {
        	currentNote = currSong.getNext();
        }
        
        if(skill.equals("Find Key for Note"))
        {
        	staffPanel.setNote(currentNote);
        	staffPanel.invalidate();
        	staffPanel.repaint();
        }
        else if(skill.equals("Find Note for Key"))
        {
        	keyboardPanel.setNewKey(currentNote);
        }
    }
    
    public NoteSynthesizer getNoteSynthesizer() {
        return synthesizer;
    }

    public ControlPanel getControlPanel() {
        return controlPanel;
    }
    
    public Key getCurrentKey() {
        return currentKey;
    }

    public GUI getGui() {
        return gui;
    }

    public KeyboardPanel getKeyboardPanel() {
        return keyboardPanel;
    }
    
    
    public ResultsPanel getResultsPanel() {
        return resultsPanel;
    }

    public String getSkill() {
        return skill;
    }

    public String getSong() {
        return song;
    }

    public StaffPanel getStaffPanel() {
        return staffPanel;
    }

    public void setCurrentKey(Key lastKeyClicked) {
    	this.lastKeyClicked = lastKeyClicked;
        this.synthesizer.playNote(Note.valueOf(this.lastKeyClicked.getName()));

        if(skill.equals("Find Key for Note")){
            if(this.currentNote == Note.valueOf(this.lastKeyClicked.getName())){
            	
                this.lastKeyClicked.setKeyColor(Color.yellow);
                this.lastKeyClicked.repaint();
                
                this.resultsPanel.incrementScore();
                this.resultsPanel.incrementTotal();
                this.generateNewNoteandKey();
            }else{
                this.lastKeyClicked.setKeyColor(Color.RED);
                this.lastKeyClicked.repaint();
                
                this.resultsPanel.incrementTotal();
            }
            this.lastKeyClicked.clearAfterMilli(300);
        }else if(skill.equals("Find Key for Tone")){
            if(this.currentNote == Note.valueOf(this.lastKeyClicked.getName())){
            	
                this.lastKeyClicked.setKeyColor(Color.yellow);
                this.lastKeyClicked.repaint();
                 this.resultsPanel.incrementScore();
                this.resultsPanel.incrementTotal();
                this.generateNewNoteandKey();
            }else{
                this.lastKeyClicked.setKeyColor(Color.RED);
                this.lastKeyClicked.repaint();
                this.synthesizer.playNote(currentNote, 300);
                this.resultsPanel.incrementTotal();
            }
            this.lastKeyClicked.clearAfterMilli(500);
            
        }
    }
    
    public void setCurrentStaffButton(StaffButton lastStaffButtonClicked) {
        this.lastStaffButtonClicked = lastStaffButtonClicked;
        this.synthesizer.playNote(Note.valueOf(this.lastStaffButtonClicked.getName()));
        
        if(skill.equals("Find Note for Key"))
        {
        	if(this.currentNote == Note.valueOf(this.lastStaffButtonClicked.getName()))
        	{
        		this.resultsPanel.incrementScore();
                this.resultsPanel.incrementTotal();
                this.generateNewNoteandKey();
                this.keyboardPanel.setNewKey(currentNote);
        	}
        	else
        	{
        		this.resultsPanel.incrementTotal();
        		this.keyboardPanel.highlightWrongKey(Note.valueOf(this.lastStaffButtonClicked.getName()));
        	}
        }
        else if(skill.equals("Find Note for Tone"))
        {
        	if(this.currentNote == Note.valueOf(this.lastStaffButtonClicked.getName()))
        	{
        		this.resultsPanel.incrementScore();
        		this.resultsPanel.incrementTotal();
        		
        		this.generateNewNoteandKey();
        		this.synthesizer.playNote(currentNote,300);
        	}
        	else
        	{
        		this.synthesizer.playNote(currentNote, 300);
                this.resultsPanel.incrementTotal();
        	}
        }
        
        System.out.printf("Controller: StaffButton %s clicked.%n", lastStaffButtonClicked.getName());
    }

    public void setGui(GUI gui) {
        this.gui = gui;
    }

    void setSkill(String skill) {
        this.skill = skill;
        
        if(skill.equals("Find Key for Note")){
            //this.generateNewNoteandKey();
        }else if(skill.equals("Find Key for Tone")){
            //this.generateNewNoteandKey();
        }
        
        System.out.printf("Controller: New skill is [%s].%n", skill);
    }
    
    void setSong(String song) {
        this.song = song;
        for(Song s : songList)
        {
        	if(song.equals(s.getName()))
        	{
        		currSong = s;
        		return;
        	}
        }
        System.out.printf("Controller: New song is [%s].%n", song);
    }
    
    public void loadSongs()
    {
        // have songs in a seperate src folder named songs?
        
        // could make a check on currFile.getName().endsWith(".song")
        // and have only songs with proper extension added.
        //generate song for random mode
        Random generator = new Random();
        Note[] tempNotes = new Note[RAN_LENGTH];
        for(int i = 0; i < RAN_LENGTH; i++){
            tempNotes[i] = Note.values()[generator.nextInt(11)];
        }
        Song ranSong = new Song("Random", tempNotes);
        songList.add(ranSong);
        File songFolder = new File("src/urnoted/songs/");
        for (File currFile : songFolder.listFiles()){
            if(currFile.getName().startsWith(".") || currFile.getName().equals("")) {continue;}
            Song newSong = new Song(currFile);
            if(!newSong.getName().equals(""))
            	songList.add(newSong);     
        }
        Collections.sort(songList);
    }

    // Restarts with new skill an/or new song:
    void start() {
    	this.currSong.reset();
    	this.generateNewNoteandKey();
        this.resultsPanel.resetScore();
        this.staffPanel.repaint();
        if(!skill.equals("Find Note for Key"))
        	this.keyboardPanel.resetKeys();
        this.keyboardPanel.repaint();
        
        if(skill.equals("Find Key for Tone") || skill.equals("Find Note for Tone"))
        {
        	this.synthesizer.playNote(currentNote, 300);
        }
    }
    
    public ArrayList<Song> getSongList()
    {
    	return songList;
    }
}
